package com.axs.logcollector.jira;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;

import org.apache.log4j.Logger;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.joda.time.DateTime;

import com.atlassian.jira.rest.client.api.JiraRestClient;
import com.atlassian.jira.rest.client.api.SearchRestClient;
import com.atlassian.jira.rest.client.api.domain.BasicUser;
import com.atlassian.jira.rest.client.api.domain.Comment;
import com.atlassian.jira.rest.client.api.domain.Issue;
import com.atlassian.jira.rest.client.api.domain.IssueField;
import com.atlassian.jira.rest.client.api.domain.SearchResult;
import com.atlassian.jira.rest.client.api.domain.User;
import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory;
import com.atlassian.util.concurrent.Promise;
import com.axs.logcollector.LogCollector;
public class JiraManagementService {
	private static final Logger m_log = Logger.getLogger(JiraManagementService.class);
	
	private static final URI DEFAULT_JIRA_SERVER = URI.create("http://tiger.in.alcatel-lucent.com:8091");

	public Promise<Issue> getIssue(String ticketId, String jiraAddress, String userName, String password) {
		JiraRestClient restClient = getJiraConnection(URI.create(jiraAddress), userName, password);
		Promise<Issue> issue = restClient.getIssueClient().getIssue(ticketId);
		return issue;
	}

	private JiraRestClient getJiraConnection(URI jiraAddress, String userName, String password) {
		try {
			AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
			if (jiraAddress == null) {
				jiraAddress = DEFAULT_JIRA_SERVER;
			}
			return factory.createWithBasicHttpAuthentication(jiraAddress, userName, password);
		} catch (Exception e) {
			m_log.info("Could not access JIRA server: " + jiraAddress.toString());
		}
		return null;
	}

	public void addAttachment(LogCollector logCollector, String compressedLogFile) {
		JiraRestClient restClient = getJiraConnection(URI.create(logCollector.getJiraAddress()), logCollector.getJiraUserName(), 
				logCollector.getJiraPassword());
		Promise<Issue> issue = restClient.getIssueClient().getIssue(logCollector.getTicketId());
		
		InputStream compressedLogFileStream = null; 
		try {
			m_log.info("Attaching logs to JIRA server " + logCollector.getJiraAddress() + " on ticket " + logCollector.getTicketId());
			compressedLogFileStream = new FileInputStream(compressedLogFile);
			restClient.getIssueClient().addAttachment(issue.get().getAttachmentsUri(), compressedLogFileStream , logCollector.getLogName()); 
		} catch (Exception e) {
			m_log.info("Error in attaching logs: " + e);
		} finally {
			try {
				if (compressedLogFileStream != null) {
					compressedLogFileStream.close();
				}
			} catch (IOException e) {
				m_log.error("Could not attach logs to " + logCollector.getJiraAddress(), e);
			}
		}
	}
	
	public void addComment(LogCollector logCollector) {
		JiraRestClient restClient = getJiraConnection(URI.create(logCollector.getJiraAddress()), logCollector.getJiraUserName(), 
				logCollector.getJiraPassword());
		Promise<Issue> issue = restClient.getIssueClient().getIssue(logCollector.getTicketId());
		
		try {
			URI self = issue.get().getCommentsUri();
			User assignee = issue.get().getAssignee();
			BasicUser author = new BasicUser(self, assignee.getDisplayName(), assignee.getName());
			BasicUser updateAuthor = new BasicUser(self, assignee.getDisplayName(), assignee.getName());
			Comment comment = new Comment(self, logCollector.getComment(), author, updateAuthor, new DateTime(), null, null, null);
			restClient.getIssueClient().addComment(issue.get().getCommentsUri(), comment);
			m_log.info("Commend is addded on ticket " + logCollector.getTicketId());
		} catch (Exception e) {
			m_log.error("Could not add comment on JIRA ticket " + logCollector.getTicketId(), e);
		}
	}

	List<Ticket> getTickets(String address, String userName, String password, String status) {
		JiraRestClient restClient = getJiraConnection(URI.create(address), userName, password);
		//Promise<Issue> issue = restClient.getIssueClient().getIssue(logCollector.getTicketId());
		
		SearchRestClient searchClient = restClient.getSearchClient();
		String jql = "reporter = " + userName + " AND status in (" + status + ")  ORDER BY createdDate DESC";
		SearchResult searchResult = searchClient.searchJql(jql).claim();
		m_log.info("JQL: " + jql + " - Total result: " + searchResult.getTotal() + " ticket(s)");
		List<Ticket> tickets = new ArrayList<Ticket>();
		for (Issue issue : searchResult.getIssues()) {
			Ticket ticket = new Ticket();
			ticket.setTicketId(issue.getKey());
			ticket.setSummary(issue.getSummary());
			ticket.setIssueType(issue.getIssueType());
			ticket.setPriority(issue.getPriority());
			IssueField testAssigneeField = issue.getFieldByName("Test Assignee");
			if (testAssigneeField != null) {
				try {
					JSONObject jsonObject = (JSONObject) testAssigneeField.getValue();
					if (jsonObject != null) {
						ticket.setTestAssignee(jsonObject.getString("displayName"));
					} 
				} catch (JSONException e) {
				}
			}
			if (issue.getAssignee() != null) {
				ticket.setAssignee(issue.getAssignee().getDisplayName());
			}
			ticket.setReporter(issue.getReporter().getDisplayName());
			ticket.setStatus(issue.getStatus());
			m_log.info("Ticket info: " + ticket.toString());
			tickets.add(ticket);
		}
		return tickets;
	}
	
	public static void main(String[] args) throws IOException, InterruptedException, ExecutionException, JSONException {
		final AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
		final JiraRestClient restClient = factory.createWithBasicHttpAuthentication(DEFAULT_JIRA_SERVER, "knguyenn", "s1515_k1515");
		try {
			/*Promise<Issue> issue = restClient.getIssueClient().getIssue("CONV-75362");
			 
			URI self = issue.get().getCommentsUri();
			String body = "Add comment - Test only 1";
			BasicUser author = new BasicUser(self, issue.get().getAssignee().getDisplayName(), issue.get().getAssignee().getName());
			BasicUser updateAuthor = new BasicUser(self, issue.get().getAssignee().getDisplayName(), issue.get().getAssignee().getName());
			DateTime creationDate = new DateTime();
			DateTime updateDate = null;
			Visibility visibility = null;
			Long id = null;
			Comment comment = new Comment(self, body, author, updateAuthor, creationDate, updateDate, visibility, id);
			m_log.info(comment);
			restClient.getIssueClient().addComment(issue.get().getCommentsUri(), comment);
			
			User assignee = issue.get().getAssignee();
			m_log.info("User: " + assignee.getDisplayName());
			// Attach files 
			m_log.info("attaching file ....");
			InputStream file = new FileInputStream("C:\\Test.xml");
			restClient.getIssueClient().addAttachment(issue.get().getAttachmentsUri(), file , "Test_1.xml");*/ 
			
			// Search tickets 
			
			SearchRestClient searchClient = restClient.getSearchClient();
			String jql = "reporter = " + "knguyenn" + " AND status in (Closed)  ORDER BY createdDate DESC";
			System.out.println("Query: " + jql);
			SearchResult searchResult = searchClient.searchJql(jql).claim();
			System.out.println("Total result: " + searchResult.getTotal());
			
			List<Ticket> tickets = new ArrayList<Ticket>();
			for (Issue issue : searchResult.getIssues()) {
				Ticket ticket = new Ticket();
				ticket.setTicketId(issue.getKey());
				ticket.setSummary(issue.getSummary());
				ticket.setIssueType(issue.getIssueType());
				ticket.setPriority(issue.getPriority());
				IssueField fieldByName = issue.getFieldByName("Test Assignee");
				if (fieldByName != null) {
					JSONObject jsonObject = (JSONObject) fieldByName.getValue();
					if (jsonObject != null) {
						ticket.setTestAssignee(jsonObject.getString("displayName"));
					}
				}
				if (issue.getAssignee() != null) {
					ticket.setAssignee(issue.getAssignee().getDisplayName());
				}
				ticket.setReporter(issue.getReporter().getDisplayName());
				ticket.setStatus(issue.getStatus());
				System.out.println(ticket.toString() + "\n");
				tickets.add(ticket);
			}

		} finally {
			//restClient.close();
		}
	}
}
